const path = require('path');
const fs = require('fs');

class StringBuilder {

    constructor(str) {
        this._str = str || "";
    }

    append(str) {
        this._str += str;
    }

    appendLine(str) {
        this._str += `${str}\n`;
    }

    toStr() {
        return this._str;
    }
}

class ComponentsBuilder {

    constructor() {
        this._comps = [];
        this._imports = [];
    }

    addComp(name, file) {
        if (name == "index" || name == "Index") {
            name = path.dirname(file);
            if (name.indexOf("/")) {
                name = name.split('/');
                name = name[name.length - 1];
            }
            else if (name.indexOf("\\")) {
                name = name.split('\\');
                name = name[name.length - 1];
            }
        }

        this._imports.push(`import ${name} from "${file}";`);
        this._comps.push(`    { name: "${name}", comp: ${name}, file: "${file}"}`);
    }

    getCompCount() {
        return this._comps.length;
    }

    build() {
        let sb = new StringBuilder();

        sb.appendLine("/*");
        sb.appendLine("此文件为自动生成，请在终端执行 npm run scan 命令进行更新");
        sb.append("最后更新时间：");
        sb.appendLine(new Date())
        sb.appendLine("*/");
        sb.appendLine("");

        for (let i = 0; i < this._imports.length; i++) {
            sb.appendLine(this._imports[i]);
        }
        sb.appendLine("")

        sb.appendLine("const comps = [");
        for (let i = 0; i < this._comps.length; i++) {
            sb.append(this._comps[i]);
            if (i != this._comps.length - 1) {
                sb.appendLine(",");
            }
        }
        sb.appendLine("];");

        sb.appendLine("")
        sb.appendLine("export function getComponents() {");
        sb.appendLine("    return comps;");
        sb.appendLine("}");

        sb.appendLine("")
        sb.appendLine("export function install(app) {");
        sb.appendLine("    comps.forEach(ele => {");
        sb.appendLine("        app.component(ele.name, ele.comp);");
        sb.appendLine("    });");
        sb.appendLine("}");

        sb.appendLine("")
        sb.appendLine("export default {");
        sb.appendLine("    getComponents,");
        sb.appendLine("    install,");
        sb.appendLine("}");

        return sb.toStr();
    }
}

function loadFilesInDir(files, dir) {
    let items = fs.readdirSync(dir);
    items.forEach(ele => {
        let fullPath = `${dir}\\${ele}`;
        let info = fs.statSync(fullPath);
        if (info.isDirectory()) {
            loadFilesInDir(files, fullPath);
        }
        else {
            files.push(fullPath);
        }
    });
}

function scan(dir) {
    console.debug("正在扫描可用组件...");
    //TODO: 此处无法获取外部传入的参数，因此，目前所有的comp采用固定目录的方式进行，必须是在 src/components 目录下
    let componentsDir = path.join(__dirname, dir);
    if (__dirname.indexOf("node_modules") >= 0) {
        componentsDir = path.join(__dirname, "../../", dir);
    }
    if (!fs.existsSync(componentsDir)) {
        console.warn(`目标路径：${componentsDir} 不存在`);
        return;
    }
    console.log(`当前扫描的文件目录为：${componentsDir}`);
    let files = [];
    loadFilesInDir(files, componentsDir);

    let componentsBuilder = new ComponentsBuilder();

    files.forEach(file => {
        let extName = path.extname(file);
        if (extName != '.vue') return;
        console.debug(`正在注册：${file}`);
        let fileName = path.basename(file).replace(extName, "");
        let relPath = file.replace(componentsDir + "\\", "./").replace(/\\/g, "/");
        componentsBuilder.addComp(fileName, relPath);
    });

    let indexJsFile = path.join(componentsDir, "index.js");
    if (fs.existsSync(indexJsFile)) {
        try {
            fs.rmSync(indexJsFile);
        }
        catch (e) {
            fs.unlinkSync(indexJsFile);
        }
    }
    let indexJs = fs.createWriteStream(indexJsFile, { encoding: 'utf-8' });
    indexJs.write(componentsBuilder.build());
    indexJs.close();

    console.log(`组件注册完毕，共计：${componentsBuilder.getCompCount()} 个`);
    console.log(`文件路径为：${indexJsFile}`);
}

let dir = process.argv[2];
if (dir) {
    scan(dir);
}
else {
    console.warn("请输入需要扫描的路径");
}